package edu.zju.gis.dbfg.tileserver;

import edu.zju.gis.dbfg.tileserver.config.CommonSetting;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import static sun.nio.ch.IOStatus.EOF;

/**
 * @author Hu
 * @date 2019/9/5
 * 地图瓦片服务
 **/
@Controller
@RequestMapping("/tileservice")
@CrossOrigin
public class TileServer {
    @Autowired
    private CommonSetting setting;

    public static final String GEOJSON_MIME_TYPE = "application/vnd.mapbox-vector-tile";

    /**
     * 根据x,y,z获取GeoJSON格式瓦片数据
     */
    @RequestMapping(value = "/{serviceId}/geojson/{z}/{x}/{y}", method = RequestMethod.GET)
    @ResponseBody
    public void getGeoJsonTile(@PathVariable("serviceId")String serviceId, @PathVariable("z") Integer z,
                               @PathVariable("y") Integer y, @PathVariable("x") Integer x,
                               HttpServletResponse response) throws IOException {
        response.setContentType(GEOJSON_MIME_TYPE);
        ServletOutputStream outputStream = response.getOutputStream();
        int ty =(int)(Math.pow(2, z)-1-y);
        String path = String.format("C:\\Users\\ZJU\\tile\\%s\\%s_%s.mvt", z, x, ty);
        File tile = new File(path);
        if (tile.exists()) {
            if (tile.canRead()){
                long filesize = tile.length();
                if(filesize > Integer.MAX_VALUE) {
                    throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + filesize);
                }
                int size = (int)filesize;
                response.setContentLengthLong(size);
                FileInputStream fis = new FileInputStream(tile);
                byte[] bytes=new byte[size];
                // 读取文件所有的字节并返回
                int offset = 0;
                int readed;
                while (offset < size && (readed = fis.read(bytes, offset, size-offset)) != EOF) {
                    offset += readed;
                }
                if (offset != size) {
                    throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
                }
                IOUtils.write(bytes, outputStream);
                outputStream.flush();
                outputStream.close();
            } else {
                byte[] msg = String.format("Geojson tile [%d, %d, %d] can not read", z, x, y).getBytes();
                IOUtils.write(msg, outputStream);
                response.setContentLength(msg.length);
                response.setStatus(500);
            }
        } else {
            byte[] msg = String.format("Geojson tile [%d, %d, %d] not exists", z, x, y).getBytes();
            IOUtils.write(msg, outputStream);
            response.setContentLength(msg.length);
            response.setStatus(404);
        }

    }

    @RequestMapping(value = "/pic/{z}/{x}/{y}", method = RequestMethod.GET)
    @ResponseBody
    public void getJPGTile(@PathVariable("z") Integer z,
                           @PathVariable("y") Integer y, @PathVariable("x") Integer x,
                           HttpServletResponse response) throws IOException {
        ServletOutputStream outputStream = response.getOutputStream();
        String path = setting.getBaseMapRoot() + String.format("/%s/%s/%s.jpg", z, x, y);
        File tile = new File(path);
        if (tile.exists()) {
            if (tile.canRead()) {
                long filesize = tile.length();
                if (filesize > Integer.MAX_VALUE) {
                    throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + filesize);
                }
                int size = (int) filesize;
                response.setContentLengthLong(size);
                FileInputStream fis = new FileInputStream(tile);
                byte[] bytes = new byte[size];
                // 读取文件所有的字节并返回
                int offset = 0;
                int readed;
                while (offset < size && (readed = fis.read(bytes, offset, size - offset)) != EOF) {
                    offset += readed;
                }
                if (offset != size) {
                    throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
                }
                IOUtils.write(bytes, outputStream);
                outputStream.flush();
                outputStream.close();
            } else {
                byte[] msg = String.format("tile [%d, %d, %d] can not read", z, x, y).getBytes();
                IOUtils.write(msg, outputStream);
                response.setContentLength(msg.length);
                response.setStatus(500);
            }
        } else {
            byte[] msg = String.format("tile [%d, %d, %d] not exists", z, x, y).getBytes();
            IOUtils.write(msg, outputStream);
            response.setContentLength(msg.length);
            response.setStatus(404);
        }

    }


}
